from flask import jsonify, render_template, Blueprint, request
import pandas as pd
from my_const import *

from util.log_util import get_the_logger

logger = get_the_logger(__name__)

fund_chart_bp = Blueprint('fund_chart', __name__)


# ---------------------- 辅助函数：读取基金原始数据 ----------------------
def load_fund_raw_data(fund_code):
    """读取基金CSV原始数据，返回带日期索引的DataFrame"""
    period = 'daily'
    csv_path = os.path.join(HISTORY_DIR, f'{fund_code}-{period}.csv')
    try:
        df = pd.read_csv(csv_path)
        # 转换日期列为索引（确保与策略函数的df格式一致）
        df["净值日期"] = pd.to_datetime(df["净值日期"])
        df.set_index("净值日期", inplace=True)
        return df
    except Exception as e:
        logger.error(f"读取基金{fund_code}数据失败：{str(e)}")
        return None


# ---------------------- 辅助函数：读取提前保存的走势+买入点CSV ----------------------
def load_chart_data_from_csv(fund_code, strategy_name="ma", ma_range=DEFAULT_MA_DAYS):
    """
    从CSV读取基金走势和买入点数据（替代执行策略）
    :param fund_code: 基金代码
    :param strategy_name: 策略名（ma/drop，默认ma）
    :param ma_range: MA策略的均线天数（默认30，drop策略忽略）
    :return: net_values（走势）、buy_points（买入点）、strategy_metrics（简化指标）
    """

    if strategy_name == "ma":
        csv_filename = f"{fund_code}_{strategy_name}_{ma_range}d.csv"
    else:
        csv_filename = f"{fund_code}_{strategy_name}.csv"

    csv_path = os.path.join(BACKTEST_DIR, csv_filename)

    try:
        df = pd.read_csv(csv_path, encoding="utf-8-sig")
    except Exception as e:
        logger.error(f"Failed to read fund {fund_code}：{str(e)}")
        return None, None, None

    # 1. 提取净值走势数据（日期+单位净值）
    net_values = {
        "dates": df["date"].tolist(),
        "net_values": df["net_value"].tolist()
    }

    # 2. 提取买入点数据（筛选is_buy=True的行）
    df_buy = df[df["is_buy"] == True].copy()
    buy_points = {
        "dates": df_buy["date"].tolist(),
        "prices": df_buy["buy_price"].tolist(),
        "costs": df_buy["buy_cost"].tolist()
    }

    # 3. 提取简化的策略指标（总投入、总买入次数等，从买入点数据计算）
    total_return = df_buy["buy_units"].sum() * df.iloc[-1]["net_value"]
    logger.info(total_return)
    total_cost = df_buy["buy_cost"].sum()
    logger.info(total_cost)
    if total_cost == 0:
        total_return_rate = 0
    else:
        total_return_rate = round((total_return - total_cost) * 100 / total_cost, 2)
    total_buy_times = len(df_buy)

    # （可选）如果需要年化收益率，可从评估结果JSON中读取，这里简化为0（或留空）
    # 若要精确指标，可在save_fund_chart_data时同步保存年化收益率到CSV
    strategy_metrics = {
        "total_return_rate": total_return_rate,
        "buy_times": total_buy_times
    }

    return net_values, buy_points, strategy_metrics


# ---------------------- 2. 可视化专用接口：返回走势+买入点数据 ----------------------
@fund_chart_bp.route("/api/fund/visual/<fund_code>", methods=["GET"])
def fund_visual_data(fund_code):
    """
    返回走势+买入点数据（从CSV读取，替代执行策略）
    支持通过参数指定策略（默认ma）和MA天数（默认30）
    """
    # 从请求参数中获取策略和MA天数（前端可传，默认ma+30d）
    from flask import request  # 新增：获取请求参数
    strategy_name = request.args.get("strategy", "ma")  # 策略：ma/drop
    ma_range = int(request.args.get("ma_range", DEFAULT_MA_DAYS))  # MA天数：30/60/90

    # 读取CSV数据
    net_trend, buy_points, strategy_metrics = load_chart_data_from_csv(
        fund_code=fund_code,
        strategy_name=strategy_name,
        ma_range=ma_range
    )

    # 数据不存在则返回错误
    if not net_trend:
        return jsonify({
            "success": False,
            "error": f"基金{fund_code}({strategy_name})的图表数据不存在，请先执行today.py生成"
        })

    # 整合返回（格式和之前一致，前端无需修改）
    return jsonify({
        "success": True,
        "data": {
            "net_trend": net_trend,
            "buy_points": buy_points,
            "metrics": strategy_metrics
        }
    })


# ---------------------- 3. 前端页面路由：渲染可视化页面 ----------------------
@fund_chart_bp.route("/fund/chart/<fund_code>")
def fund_chart_page(fund_code):
    """返回基金可视化页面（传入基金代码，用于前端请求数据）"""
    ma_range = request.args.get("ma_range", DEFAULT_MA_DAYS)
    return render_template("fund_chart.html", fund_code=fund_code, ma_range=ma_range)
